import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { CreateDictionaryDto } from './dto/create-dictionary.dto';
import { UpdateDictionaryDto } from './dto/update-dictionary.dto';
import { InjectEntityManager, InjectRepository } from "@nestjs/typeorm";
import { DictionaryType } from "./entities/dictionary_type.entity";
import { EntityManager, Repository } from "typeorm";
import { FindDictionaryDataDto, FindDictionaryDto } from "./dto/find-dictionary.dto";
import { DeleteIds } from "../dto/all-dto";
import { DictionaryData } from "./entities/dictionary_data.entity";
import { CreateDemoReDto } from "../demo-res/dto/create-demo-re.dto";
import { UpdateDemoReDto } from "../demo-res/dto/update-demo-re.dto";
import { distinct } from "rxjs";
@Injectable()
export class DictionaryService {
  constructor(
    @InjectRepository(DictionaryType)
    private dictTypeRepository:Repository<DictionaryType>,
    @InjectRepository(DictionaryData)
    private dictDataRepository:Repository<DictionaryData>,
    @InjectEntityManager()
    private entityManager:EntityManager
  ) {}
  async create(createDictionaryDto: CreateDictionaryDto) {
    const dictTypeBuilder = this.dictTypeRepository.createQueryBuilder()
    const {name, code, description} = createDictionaryDto

    if( await dictTypeBuilder.where("name = :name", { name: name }).getOne() ) throw new HttpException("字典名称已存在", HttpStatus.INTERNAL_SERVER_ERROR)
    if( await dictTypeBuilder.where("code = :code", { code: code }).getOne() )  throw new HttpException("字典类型已存在", HttpStatus.INTERNAL_SERVER_ERROR)

    const { identifiers } = await dictTypeBuilder.insert().values({
       name,
       code,
      ...(description && {description}),
    }).execute()
    if(identifiers.length === 0){
      throw new HttpException("添加失败", HttpStatus.INTERNAL_SERVER_ERROR)
    }
    return identifiers[0]
  }

  async findAll(findDictionaryDto:FindDictionaryDto) {
    const dictTypeBuilder = this.dictTypeRepository.createQueryBuilder()
    const {page, pageSize, name, code} = findDictionaryDto;
    if(name){
      dictTypeBuilder.andWhere("name LIKE :name", { name })
    }
    if(code){
      dictTypeBuilder.andWhere("code LIKE :code", { code })
    }
    const [list, total] = await dictTypeBuilder.orderBy('id','DESC').skip((page - 1) * pageSize).take(pageSize).getManyAndCount()
    return {
      list,
      total
    }
  }

  findOne(id: number) {
    return `This action returns a #${id} dictionary`;
  }

  async update(updateDictionaryDto: UpdateDictionaryDto) {
    const dictTypeBuilder = this.dictTypeRepository.createQueryBuilder()
    const {name, code, description} = updateDictionaryDto;
    const { affected } = await dictTypeBuilder.update().set({
      ...(name && {name}),
      ...(description && {description}),
    }).where("code = :code", { code }).execute()
    if(affected===0){
      throw new HttpException("更新失败", HttpStatus.INTERNAL_SERVER_ERROR)
    }
    return ""
  }

  async remove(deleteIds:DeleteIds) {
    let list = await this.dictDataRepository.createQueryBuilder("dictData")
      .leftJoinAndSelect("dictData.dictionaryType","dictType")
      .where("dictType.id IN (:...ids)",{ids:deleteIds.ids})
      .select("dictData.id")
      .getMany()
    let  itemIds = list.map(item=> item.id)

    const { affected }  = await this.entityManager.transaction( async transactionalEntityManager =>{
      const dataDel =  await transactionalEntityManager.createQueryBuilder().delete().from(DictionaryData).whereInIds(itemIds).execute()

      return  await transactionalEntityManager.createQueryBuilder().delete().from(DictionaryType).whereInIds(deleteIds.ids).execute();
    })
    if(affected===0){
      throw new HttpException("删除失败",HttpStatus.INTERNAL_SERVER_ERROR)
    }
    return "删除成功"
  }
}

@Injectable()
export class DictionaryDataService {
  constructor(
    @InjectRepository(DictionaryData)
    private dictDataRepository:Repository<DictionaryData>,
    @InjectRepository(DictionaryType)
    private dictTypeRepository:Repository<DictionaryType>,
  ) {}

  async create(createDemoReDto: CreateDemoReDto) {
    const {label, value, id, sort, color, rgb} = createDemoReDto;
    const dictTypeBuilder = this.dictTypeRepository.createQueryBuilder("dictType")
    const dictDataBuilder = this.dictDataRepository.createQueryBuilder("dictData")
    const typeOne = await dictTypeBuilder.where("id = :id", { id: id }).getOne()
    if(!typeOne){
      throw new HttpException("创建失败请返回刷新后重试",HttpStatus.INTERNAL_SERVER_ERROR)
    }
    /**
     * 创建了两个独立的查询构建器 dictTypeBuilder 和 dictDataBuilder，并使用它们执行操作。问题很可能来源于这些查询构建器在连续的多个查询中被重复使用，没有在后续使用中适当地重置或重新初始化别名。下面是问题的分析：
     *
     * 重复使用查询构建器：你在 dictDataBuilder 中多次执行查询，每次都使用相同的 "dictType" 别名。这可能导致在单个 SQL 语句中多次引用同一个别名而没有区分开来，从而触发了错误。
     *
     * 解决方法：
     *
     * 重新初始化查询构建器：在每次使用查询构建器进行新查询前，重新创建或清除之前的设置。这可以通过重新调用 createQueryBuilder() 来实现，以确保每个查询都是独立的，不会互相干扰。
     * 使用不同的别名：在不同的查询中为相同的表使用不同的别名，特别是在涉及多个表连接时。
     */
    if(
      await dictDataBuilder.leftJoinAndSelect("dictData.dictionaryType","dictType").where("dictType.code = :code",{code:typeOne.code}).andWhere("dictData.label = :label",{label}).getOne()
    ) throw new HttpException("字典名冲突", HttpStatus.INTERNAL_SERVER_ERROR)
    if(
      await dictDataBuilder.leftJoinAndSelect("dictData.dictionaryType","dictType2").where("dictType2.code = :code",{code:typeOne.code}).andWhere("dictData.value = :value",{value}).getOne()
    ) throw new HttpException("字典键值", HttpStatus.INTERNAL_SERVER_ERROR)
    let newSort = 0;
    if(sort){
      newSort = sort
    }else{
      newSort =  (await this.findAll({
        code: typeOne.code
      })).length
    }
    console.log(newSort,"newSort");
    await dictDataBuilder.insert().values({
      dictionaryType: typeOne,
      label,
      value,
      color,
      rgb,
      sort:newSort
    }).execute()
  }

   async findAll(findDictionaryDataDto: FindDictionaryDataDto) {
     const {code} = findDictionaryDataDto
     const dictDataBuilder = await this.dictDataRepository.createQueryBuilder("dictionaryData")
     const list = await dictDataBuilder.leftJoinAndSelect("dictionaryData.dictionaryType","dictionaryType")
       .orderBy("dictionaryData.sort","ASC")
       .where("dictionaryType.code = :code",{code})
       .getMany()
     list.forEach(item=> delete item.dictionaryType)
     return list
  }

  // async findOne(code: string) {
  // return  await this.dictDataRepository.createQueryBuilder("dictData")
  //    .select(["dictData.id","dictData.color","dictData.rgb","dictData.label","dictData.value"])
  //    .leftJoin("dictData.dictionaryType","dictionaryType")
  //    .where("dictionaryType.code = :code",{code})
  //    .getMany()
  // }

  async update(updateDemoReDto: UpdateDemoReDto) {
    const {label,value,color,sort,rgb,id} = updateDemoReDto;
    const {affected} = await this.dictDataRepository.createQueryBuilder().update().set({
      ...(label && {label}),
      ...(color && {color}),
      ...(sort && {sort}),
      ...(rgb && {rgb}),
      ...(value && {value})
    }).where("id = :id",{id}).execute()
    if(affected===0){
      throw new  HttpException("更新失败", HttpStatus.INTERNAL_SERVER_ERROR)
    }
    return "操作成功"
  }

  async remove(deleteIds: DeleteIds) {
    const {affected} = await this.dictDataRepository.createQueryBuilder().delete().whereInIds(deleteIds.ids).execute()
    if(affected===0){
      throw new  HttpException("删除失败", HttpStatus.INTERNAL_SERVER_ERROR)
    }
    return `删除成功`;
  }
}